package server

import (
	"encoding/json"
	"errors"
	"fmt"
	"gorm.io/gorm"
	"server/src/global"
	"server/src/model"
	"server/src/model/common"
	"server/src/model/request"
	"server/src/model/response"
	"server/src/utils"
	"time"
)

type guess struct{}

// 获取数据库答案最后一期的期数
func (*guess) GetAnwserId() int {
	bgAnswerNumber := &model.BgAnswerNumber{}
	err := global.GVL_DB.Last(bgAnswerNumber).Error
	if err != nil || bgAnswerNumber.Id <= 0 {
		return global.BG_INITIAL_ANSWERID
	} else {
		return bgAnswerNumber.Id
	}
}

// 获取AnswerId期全部积分总数
func (*guess) GetBgCurrentAllIntegral(AnswerId int) (sumIntergral float64, err error) {
	if AnswerId == global.BG_CURRENT_ANSWERID {
		return global.BG_CURRENT_INTERGRAL, nil
	}
	err = global.GVL_DB.Model(&model.BgAnswerNumber{}).Select("sum_intergral").Where("id = ?", AnswerId).
		First(&sumIntergral).Error
	if err != nil {
		return 0, err
	}
	return
}

// 设置本期答案到服务器中
func (*guess) SetCurrentAnswerNum(numbersStr []string, superNum int, answerNum int) error {
	numj, err := json.Marshal(numbersStr)
	if err != nil {
		return errors.New("json 出错" + err.Error())
	}
	bgAswerNumber := &model.BgAnswerNumber{
		Id:          global.BG_CURRENT_ANSWERID,
		AnswerNum:   answerNum,
		SuperNumber: superNum,
		AnswerSize:  utils.BgSize(answerNum),
		AnswerDos:   utils.BgDos(answerNum),
		AnswerFive:  utils.BgFive(global.BG_CURRENT_INTERGRAL, superNum),
		SumIntegral: global.BG_CURRENT_INTERGRAL,
		Nums:        string(numj),
		Time:        int(time.Now().Unix()),
	}

	if err := global.GVL_DB.Save(bgAswerNumber).Error; err != nil {
		return errors.New("save 出错" + err.Error())
	}
	return nil
}

// 查询本期所有竞猜数据
func (*guess) QueryBgCurrentAllBetting(answerId int) (*response.BgCurrentAllBetting, error) {
	currentAllBetting := &response.BgCurrentAllBetting{
		BgCurrentBettrings: make([]*response.OurBgCurrentBetting, 0),
	}
	bgGuess := make([]*model.BgGuess, 0)
	err := global.GVL_DB.Model(bgGuess).Where("answer_id =?", answerId).Find(&bgGuess).Error
	if err != nil {
		return nil, errors.New("bgGuess query error:" + err.Error())
	}
	for _, bgv := range bgGuess {
		newCurrentAllBetting := &response.OurBgCurrentBetting{
			Id:       bgv.Id,
			UserId:   bgv.UserId,
			AnswerId: answerId,
		}
		bgGuessNums := make([]*model.BgGuessNum, 0)
		err = global.GVL_DB.Where("guess_id =?", bgv.Id).Find(&bgGuessNums).Error
		if err != nil {
			return nil, errors.New("bgGuessNums query error:" + err.Error())
		}
		for _, bgnv := range bgGuessNums {
			newBgGuessNum := &response.BgGuessNum{
				GuessId:       bgnv.GuessId,
				Integral:      bgnv.Integral,
				PlayingMethod: bgnv.PlayingMethod,
			}
			err = json.Unmarshal([]byte(bgnv.Num), &newBgGuessNum.Num)
			if err != nil {
				return nil, errors.New("response json error:" + err.Error())
			}
			newCurrentAllBetting.BgGuessNums = append(newCurrentAllBetting.BgGuessNums, newBgGuessNum)
		}
		currentAllBetting.BgCurrentBettrings = append(currentAllBetting.BgCurrentBettrings, newCurrentAllBetting)
	}
	return currentAllBetting, nil
}

// 用户下注
func (*guess) UserBgBetting(uid int, reqInfo *request.UserBettings) error {
	// 是否在这一期以及竞猜过了
	bgGuess := &model.BgGuess{}
	tx := global.GVL_DB.Begin()
	err := tx.Model(bgGuess).Where("user_id = ? and answer_id =?", uid, reqInfo.AnswerId).First(&bgGuess).Error
	if bgGuess.Id <= 0 || err != nil {
		bgGuess.UserId = uid
		bgGuess.AnswerId = reqInfo.AnswerId
		err := tx.Create(bgGuess).Error
		if err != nil {
			tx.Rollback()
			return err
		}
	}
	jsonNum, err := json.Marshal(reqInfo.Num)
	if err != nil {
		return errors.New("JSON encoding error:" + err.Error())
	}
	bgGuessNum := &model.BgGuessNum{
		GuessId:       bgGuess.Id,
		PlayingMethod: reqInfo.PlayingMethod,
		Num:           string(jsonNum),
		Integral:      reqInfo.Integral,
		Time:          int(time.Now().Unix()),
	}
	// 检查是否已经存在该记录
	existingGuessNum := &model.BgGuessNum{}
	err = tx.Model(existingGuessNum).Where("guess_id = ? and playing_method = ? and num = ?", bgGuess.Id, reqInfo.PlayingMethod, string(jsonNum)).First(existingGuessNum).Error
	if err == nil {
		// 如果记录存在，更新积分
		bgGuessNum.Integral += existingGuessNum.Integral
		err = tx.Model(existingGuessNum).Where("guess_id = ? and playing_method = ? and num = ?", bgGuess.Id, reqInfo.PlayingMethod, string(jsonNum)).Update("integral", bgGuessNum.Integral).Error
		if err != nil {
			tx.Rollback()
			return errors.New("Failed to update existing BgGuessNum: " + err.Error())
		}
	} else if !errors.Is(err, gorm.ErrRecordNotFound) {
		// 如果发生了其他错误，回滚事务
		fmt.Println("sadfdsafisadhfiadhfakjshdfiuhwekfjchasiudj<><><>", err)
		tx.Rollback()
		return err
	} else {
		// 如果记录不存在，创建新记录
		err = tx.Create(bgGuessNum).Error
		if err != nil {
			tx.Rollback()
			return err
		}
	}
	// 修改用户总积分
	user := &model.WeChatGroupUser{}
	err = tx.Where("id =?", uid).First(&user).Error
	if err != nil || user.SumScore-reqInfo.Integral < 0 {
		tx.Rollback()
		return errors.New("积分不够" + err.Error())
	}
	err = tx.Model(&user).Where("id = ?", uid).
		Updates(map[string]interface{}{"sum_score": user.SumScore - reqInfo.Integral,
			"system_score": user.SystemScore - reqInfo.Integral}).Error
	if err != nil {
		tx.Rollback()
		return errors.New("积分不够" + err.Error())
	}
	// 修改本期的积分
	global.BG_CURRENT_INTERGRAL += reqInfo.Integral
	tx.Commit()
	return nil
}

// 取消下注
func (*guess) UserCancelBgBetting(uid int, answerId int) error {
	tx := global.GVL_DB.Begin()
	var integral int64
	if err := tx.Model(&model.BgGuess{}).Joins("JOIN bg_guess_num ON bg_guess.id = bg_guess_num.guess_id").
		Where("bg_guess.user_id = ? AND bg_guess.answer_id = ?", uid, answerId).
		Select("SUM(bg_guess_num.integral)").
		Scan(&integral).Error; err != nil {
		tx.Rollback()
		return err
	}
	bgGuess := &model.BgGuess{}
	if err := tx.Where("bg_guess.user_id = ? AND bg_guess.answer_id = ?", uid, answerId).
		First(bgGuess).Error; err != nil {
		tx.Rollback()
		return err
	}
	if err := tx.Where("bg_guess.user_id = ? AND bg_guess.answer_id = ?", uid, answerId).
		Delete(&model.BgGuess{}).Error; err != nil {
		tx.Rollback()
		return err
	}
	if err := tx.Where("guess_id = ?", bgGuess.Id).
		Delete(&model.BgGuessNum{}).Error; err != nil {
		tx.Rollback()
		return err
	}
	if err := tx.Model(&model.WeChatGroupUser{}).Where("id = ?", uid).
		Updates(map[string]interface{}{"sum_score": gorm.Expr("sum_score + ?", integral),
			"system_score": gorm.Expr("system_score + ?", integral)}).Error; err != nil {
		tx.Rollback()
		return err
	}
	tx.Commit()
	return nil
}

// 查看用户今日盈亏
func (*guess) QueryTodayPhase(uid int) (error, float64) {
	var phase float64
	var bgGuessNums []*model.BgGuessNum
	// 获取当前时间
	now := time.Now()
	// 早上 6 点的时间
	morningTimestamp := time.Date(now.Year(), now.Month(), now.Day(), 4, 0, 0, 0, now.Location()).Unix()
	// 晚上 12 点的时间
	nightTimestamp := time.Date(now.Year(), now.Month(), now.Day(), 0, 0, 0, 0, now.Location()).AddDate(0, 0, 1).Add(-time.Second).Unix()

	if err := global.GVL_DB.Model(&model.BgGuessNum{}).Joins("JOIN bg_guess ON bg_guess.id = bg_guess_num.guess_id").
		Select("bg_guess_num.*").Where("bg_guess.user_id = ? AND bg_guess_num.time > ? AND bg_guess_num.time < ?",
		uid, morningTimestamp, nightTimestamp).Find(&bgGuessNums).Error; err != nil {
		return err, 0.00
	}
	for _, v := range bgGuessNums {
		if v.IsWin == 0 {
			phase -= v.Integral
		} else if v.IsWin == 1 {
			switch v.PlayingMethod {
			case global.BG_JIAO:
				bgOod := global.BG_ODDS_JIAO - 1
				phase += float64(bgOod) * v.Integral
			case global.BG_ZHENG:
				bgOod := global.BG_ODDS_ZHENG - 1
				phase += float64(bgOod) * v.Integral
			case global.BG_FAN:
				bgOod := global.BG_ODDS_FAN - 1
				phase += float64(bgOod) * v.Integral
			case global.BG_NIAN:
				bgOod := global.BG_ODDS_NIAN - 1
				phase += float64(bgOod) * v.Integral
			}
		}
	}
	return nil, phase
}

// 判定输赢给user betting
func (g *guess) BgDetermineBetting(answerNum int) error {
	//查询下注情况
	currentAllBetting, err := g.QueryBgCurrentAllBetting(global.BG_CURRENT_ANSWERID)
	if err != nil {
		return errors.New("查询下注情况:" + err.Error())
	}

	for _, cabv := range currentAllBetting.BgCurrentBettrings {
		for _, bcabv := range cabv.BgGuessNums {
			//判断输赢
			winIntegral := 0.00
			isWin := global.BG_FAIL
			switch bcabv.PlayingMethod {
			case global.BG_JIAO:
				bgOod := global.BG_ODDS_JIAO
				if answerNum == bcabv.Num[0] || answerNum == bcabv.Num[1] {
					winIntegral += bcabv.Integral * float64(bgOod)
					isWin = global.BG_WIN
				}
				fmt.Println("jiao is:", isWin, bcabv.Integral)
			case global.BG_FAN:
				bgOod := global.BG_ODDS_FAN
				if answerNum == bcabv.Num[0] {
					winIntegral += bcabv.Integral * float64(bgOod)
					isWin = global.BG_WIN
				}
				fmt.Println("BG_FAN is:", isWin, bcabv.Integral)
			case global.BG_ZHENG:
				bgOod := global.BG_ODDS_ZHENG
				if answerNum == bcabv.Num[0] {
					winIntegral += bcabv.Integral * float64(bgOod)
					isWin = global.BG_WIN
				} else if (answerNum+2)%4 != bcabv.Num[0]%4 {
					winIntegral += bcabv.Integral * float64(global.BG_ODDS_BRAW)
					isWin = global.BG_DRAW
				}
				fmt.Println("BG_ZHENG is:", isWin, winIntegral)
			case global.BG_NIAN:
				bgOod := global.BG_ODDS_NIAN
				if answerNum == bcabv.Num[0] {
					winIntegral += bcabv.Integral * float64(bgOod)
					isWin = global.BG_WIN
				} else if answerNum == bcabv.Num[1] {
					winIntegral += bcabv.Integral * float64(global.BG_ODDS_BRAW)
					isWin = global.BG_DRAW
				}
				fmt.Println("BG_NIAN is:", isWin, bcabv.Integral)

			}
			//抽水
			//查找每个群的抽水
			pupm := 0.00
			groupUserInfo := &model.WeChatGroupUser{}
			groupInfo := &model.WeChatGroup{}
			err := global.GVL_DB.Select("gid").Where("id = ?", cabv.UserId).First(groupUserInfo).Error
			err = global.GVL_DB.Select("pump").Where("id = ?", groupUserInfo.Gid).First(groupInfo).Error
			if err != nil {
				pupm = 0.03
				err = nil
			} else {
				pupm = groupInfo.Pump
			}
			winIntegral = winIntegral - winIntegral*pupm

			//写入guess_num数据库
			if isWin != 0 {
				tx := global.GVL_DB.Begin()
				jsonNum, _ := json.Marshal(bcabv.Num)
				if err := tx.Model(&model.BgGuessNum{}).Where("guess_id = ? and num = ?", bcabv.GuessId, string(jsonNum)).
					Update("is_win", isWin).Error; err != nil {
					tx.Rollback()
					return err
				}
				if err := tx.Model(&model.WeChatGroupUser{}).Where("id = ?", cabv.UserId).
					Updates(map[string]interface{}{"sum_score": gorm.Expr("sum_score + ?", winIntegral),
						"system_score": gorm.Expr("system_score + ?", winIntegral)}).Error; err != nil {
					tx.Rollback()
					return err
				}
				// 提交事务
				tx.Commit()
			}
			//添加流水
			if err := global.GVL_DB.Model(&model.WeChatGroupUser{}).Where("id = ?", cabv.UserId).
				Updates(map[string]interface{}{
					"run_water": gorm.Expr("run_water + ?", bcabv.Integral)}).
				Error; err != nil {
				return err
			}
			//添加群组流水
			if err := global.GVL_DB.Model(&model.WeChatGroup{}).Where("id = ?", cabv.UserId).
				Updates(map[string]interface{}{
					"run_water": gorm.Expr("run_water + ?", bcabv)}).
				Error; err != nil {
				return err
			}
		}
	}
	return nil
}

// // 查询bg的历史答案
func (g *guess) QueryBgAnswersPages(pageInfo *common.PageReqInfo) (resInfo *response.QueryBgAnswersPages, err error) {
	resInfo = new(response.QueryBgAnswersPages)
	resInfo.Qbap = make([]*response.QueryBgAnswersPage, 0)
	var bgAnswerNumber []*model.BgAnswerNumber
	t := time.Now()
	todayStart := time.Date(t.Year(), t.Month(), t.Day(), 0, 0, 0, 0, t.Location()).Unix()
	db := global.GVL_DB.Model(&model.BgAnswerNumber{}).Where("time > ?", todayStart)
	resInfo.Page, err = serverComment.getPageRes(*pageInfo, db)
	if err != nil {
		fmt.Println("getPageRes设置出错", err)
		return nil, err
	}
	resInfo.Page.PageReqInfo = *pageInfo
	db = serverComment.paginate(*pageInfo, db)
	err = db.Order("id desc").Find(&bgAnswerNumber).Error
	if err != nil {
		fmt.Println("find bgAnswerNumber设置出错", err)
		return nil, err
	}
	for _, v := range bgAnswerNumber {
		gba := &response.QueryBgAnswersPage{
			AnswerId:    v.Id,
			AnswerNum:   v.AnswerNum,
			SuperNumber: v.SuperNumber,
			AnswerSize: func() string {
				if v.AnswerSize == 0 {
					return "小"
				}
				return "大"
			}(),
			AnswerDos: func() string {
				if v.AnswerDos == 0 {
					return "单"
				}
				return "双"
			}(),
		}
		resInfo.Qbap = append(resInfo.Qbap, gba)
	}
	return resInfo, nil
}

// 获取宾果本期答案数据
func (g *guess) GetBgAnswerNumber(answerId int) (*model.BgAnswerNumber, error) {
	resbgan := &model.BgAnswerNumber{}
	if err := global.GVL_DB.Where("id = ?", answerId).First(resbgan).Error; err != nil {
		return nil, err
	}
	return resbgan, nil
}

// 获取宾果前30期答案数据
func (g *guess) GetBgAnswerNumHistory() ([]*model.BgAnswerNumber, error) {
	var resbgans []*model.BgAnswerNumber
	if err := global.GVL_DB.Order("id desc").
		Offset(0).Limit(300).Find(&resbgans).Error; err != nil {
		return nil, err
	}
	return resbgans, nil
}

// 获取长龙
func (g *guess) GetBgChangLong(key string, value int) []*response.GetChangLong {
	reqInfo := make([]*response.GetChangLong, 0)
	for i := 0; i < 30; i++ {
		bcl := &response.GetChangLong{}
		yesterday := time.Now().AddDate(0, 0, -i)
		bcl.Time = int(yesterday.Unix())
		startOfYesterday := time.Date(yesterday.Year(), yesterday.Month(), yesterday.Day(), 0, 0, 0, 0, yesterday.Location())
		endOfYesterday := time.Date(yesterday.Year(), yesterday.Month(), yesterday.Day(), 23, 59, 59, 999999999, yesterday.Location())
		var streaks []*model.BgAnswerNumber
		// Assuming your DB table name is "bg_answer_numbers"
		// Replace "bg_answer_numbers" with your actual table name if it's different
		err := global.GVL_DB.Where("time >= ? AND time <= ? AND "+key+" = ?", startOfYesterday.Unix(), endOfYesterday.Unix(), value).
			Order("id desc").Find(&streaks).Error
		if err != nil {
			fmt.Println("获取长龙 数据库查找数据失败", err)
			continue
		}
		fmt.Println("获取长龙", streaks)
		currentId := -1
		currentCount := 1
		for _, streak := range streaks {

			fmt.Println("currentId", currentId, ".currentCount", currentCount)
			if streak.Id == currentId-1 {
				currentCount++
				switch currentCount {
				case 2:
					bcl.L2 += 1
				case 3:
					bcl.L3 += 1
				case 4:
					bcl.L4 += 1
				case 5:
					bcl.L5 += 1
				case 6:
					bcl.L6 += 1
				case 7:
					bcl.L7 += 1
				case 8:
					bcl.L8 += 1
				}
			} else {
				currentCount = 1
			}
			currentId = streak.Id
		}
		reqInfo = append(reqInfo, bcl)
	}
	return reqInfo
}
